package com.gxuwz.annotation;

import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gxuwz.entity.User;
import com.gxuwz.entity.UserOperateLog;
import com.gxuwz.service.IUserOperateLogService;
import com.gxuwz.util.DateUtils;
import com.gxuwz.util.SessionUtils;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class UserOperateLogAspect {
	
	private UserOperateLog log = null;
	
    // 本地异常日志记录对象  
    private static final Logger logger = LoggerFactory.getLogger(UserOperateLogAspect.class);
	
	@Autowired
	private IUserOperateLogService userOperateLogService;
    
	@Pointcut("@annotation(com.gxuwz.annotation.OperateAfterThrowingLog)")
	public void operateAfterThrowingAspect() {
	}
	
	@Pointcut("@annotation(com.gxuwz.annotation.OperateBeforeLog)")
	public void operateBeforeAspect() {
	}
	
	@Pointcut("@annotation(com.gxuwz.annotation.OperateAfterLog)")
	public void operateAfterAspect() {
	}
	
	public void setLogParams(UserOperateLog log,User user){
		HttpServletRequest request = SessionUtils.getRequest();  
		log.setIpAddress(request.getRemoteAddr());
		log.setUsername(user.getUsername());
		log.setRealName(user.getName());
		log.setCreateDate(DateUtils.getNowDefaultFormat());
	}
	
    /** 
     * 前置通知 记录方法执行之前的操作 
     * 
     * @param joinPoint 切点 
     */
    @Before("operateBeforeAspect()")  
    public void doBefore(JoinPoint joinPoint) { 
		try {
			OperateBeforeLog controllerLog = getController(joinPoint);
			User user = SessionUtils.getLoginUser();
			if (null == user || null == controllerLog) {
				return;
			}
			log = new UserOperateLog();
			setLogParams(log,user);
            log.setExceptionCode( null);    
            log.setExceptionDetail(null); 
			log.setMsg(controllerLog.description());
			//保存日志对象
			userOperateLogService.insert(log);
		} catch (Exception e) {
            //记录本地异常日志  
            logger.error("==前置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());
            e.printStackTrace();
		}
    }
    
    /** 
     * 后置通知 记录方法执行之前的操作
     * 
     * @param joinPoint 切点 
     */
    @After("operateAfterAspect()")  
    public void doAfter(JoinPoint joinPoint) { 
		try {
			OperateAfterLog controllerLog = getAfter(joinPoint);
			User user = SessionUtils.getLoginUser();
			if (null == user || null == controllerLog) {
				return;
			}
			log = new UserOperateLog();
			setLogParams(log,user);
            log.setExceptionCode( null);    
            log.setExceptionDetail(null); 
			log.setMsg(controllerLog.description());
			//保存日志对象
			userOperateLogService.insert(log);
		} catch (Exception e) {
            //记录本地异常日志  
            logger.error("==前置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());
            e.printStackTrace();
		}
    }

    /** 
     * 异常通知 用于记录异常日志 
     * 抛出异常时调用
     * @param joinPoint 
     * @param e 
     */  
    @AfterThrowing(pointcut = "operateAfterThrowingAspect()", throwing = "e")  
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
		try {
			OperateAfterThrowingLog serviceLog = getService(joinPoint);
			User user = SessionUtils.getLoginUser();
			if (null == user || null == serviceLog) {
				return;
			}
			log = new UserOperateLog();
			setLogParams(log,user);
            log.setExceptionCode(e.getClass().getName());  
            log.setExceptionDetail(e.getMessage());  
			log.setMsg(serviceLog.description());
			//保存日志对象
			userOperateLogService.insert(log);
		} catch (Exception ex) {
            //记录本地异常日志  
            logger.error("==前置通知异常==");  
            logger.error("异常信息:{}", ex.getMessage()); 
		}
	}
    
    public static Method getMethod(JoinPoint joinPoint){
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		return methodSignature.getMethod();
    }

	private static OperateBeforeLog getController(JoinPoint joinPoint) throws Exception {
		Method method = getMethod(joinPoint);
		if (method != null) {
			return method.getAnnotation(OperateBeforeLog.class);
		}
		return null;
	}
	
	private static OperateAfterThrowingLog getService(JoinPoint joinPoint) throws Exception {
		Method method = getMethod(joinPoint);
		if (method != null) {
			return method.getAnnotation(OperateAfterThrowingLog.class);
		}
		return null;
	}
	
	private static OperateAfterLog getAfter(JoinPoint joinPoint) throws Exception {
		Method method = getMethod(joinPoint);
		if (method != null) {
			return method.getAnnotation(OperateAfterLog.class);
		}
		return null;
	}

}
